package com.hxx.sbMyBatis.config.springtransaction;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;

/**
 * 编程式事务处理器
 * 支持：
 * - 同线程内注册事务操作
 * - 手动触发持久化
 * - 自动提交/回滚
 * - 生命周期日志追踪
 */
public class TransactionEngine {
    private static final Logger log = LoggerFactory.getLogger(TransactionEngine.class);

    private final DataSourceTransactionManager transactionManager;

    // 使用 ThreadLocal 封装事务上下文
    private final ThreadLocal<TransactionContext> contextHolder = ThreadLocal.withInitial(TransactionContext::new);

    public TransactionEngine(DataSource dataSource) {
        this.transactionManager = new DataSourceTransactionManager(dataSource);
    }

    /**
     * 注册单个事务操作
     */
    public void register(Runnable operation) {
        if (operation == null) {
            throw new IllegalArgumentException("Operation cannot be null");
        }
        ensureTransactionStarted();
        contextHolder.get().operations.add(operation);
        log.debug("[TX] Registered single operation. Total: {}", getRegisteredOperationCount());
    }

    /**
     * 注册多个事务操作
     */
    public void register(List<Runnable> operations) {
        if (operations == null || operations.isEmpty()) {
            throw new IllegalArgumentException("Operations cannot be null or empty");
        }
        ensureTransactionStarted();
        contextHolder.get().operations.addAll(operations);
        log.debug("[TX] Registered {} operations. Total: {}", operations.size(), getRegisteredOperationCount());
    }

    /**
     * 手动触发持久化
     */
    public void persistence() {
        log.info("[TX] Starting persistence in thread: {}", Thread.currentThread().getName());
        try {
            executeAllOperations();
            commitTransaction();
            log.info("[TX] Transaction committed successfully.");
        } catch (Exception e) {
            rollbackTransaction();
            log.error("[TX] Transaction rolled back due to error: {}", e.getMessage(), e);
            throw new TransactionException("Transaction execution failed", e);
        } finally {
            cleanup();
            log.debug("[TX] Transaction context cleaned up for thread: {}", Thread.currentThread().getName());
        }
    }

    /**
     * 执行所有注册的操作
     */
    private void executeAllOperations() {
        TransactionContext ctx = contextHolder.get();
        if (ctx.operations.isEmpty()) {
            log.warn("[TX] No registered operations found — skipping execution.");
            return;
        }

        log.info("[TX] Executing {} registered operations...", ctx.operations.size());
        for (int i = 0; i < ctx.operations.size(); i++) {
            try {
                log.debug("[TX] -> Executing operation [{} / {}]", i + 1, ctx.operations.size());
                ctx.operations.get(i).run();
            } catch (Exception e) {
                log.error("[TX] Operation [{}] failed: {}", i, e.getMessage(), e);
                throw new TransactionException("Operation " + i + " execution failed", e);
            }
        }
        log.debug("[TX] All operations executed successfully.");
    }

    /**
     * 提交事务
     */
    private void commitTransaction() {
        TransactionContext ctx = contextHolder.get();
        if (ctx.transactionStatus != null && !ctx.transactionStatus.isCompleted()) {
            transactionManager.commit(ctx.transactionStatus);
        } else {
            log.warn("[TX] Commit skipped: no active transaction or already completed.");
        }
    }

    /**
     * 回滚事务
     */
    private void rollbackTransaction() {
        TransactionContext ctx = contextHolder.get();
        if (ctx.transactionStatus != null && !ctx.transactionStatus.isCompleted()) {
            transactionManager.rollback(ctx.transactionStatus);
        } else {
            log.warn("[TX] Rollback skipped: no active transaction or already completed.");
        }
    }

    /**
     * 初始化事务（若未启动）
     */
    private void ensureTransactionStarted() {
        TransactionContext ctx = contextHolder.get();
        if (ctx.transactionStatus == null) {
            DefaultTransactionDefinition def = new DefaultTransactionDefinition();
            def.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED);
            def.setIsolationLevel(DefaultTransactionDefinition.ISOLATION_READ_COMMITTED);
            def.setTimeout(30);

            ctx.transactionStatus = transactionManager.getTransaction(def);
            log.debug("[TX] Transaction started in thread: {}", Thread.currentThread().getName());
        }
    }

    /**
     * 清理上下文
     */
    private void cleanup() {
        contextHolder.remove();
    }

    /**
     * 当前线程是否有事务
     */
    public boolean hasActiveTransaction() {
        return contextHolder.get().transactionStatus != null;
    }

    /**
     * 当前注册的操作数
     */
    public int getRegisteredOperationCount() {
        return contextHolder.get().operations.size();
    }

    /**
     * 内部事务上下文封装
     */
    private static class TransactionContext {
        private TransactionStatus transactionStatus;
        private final List<Runnable> operations = new ArrayList<>();
    }
}
